const hasOwn = Object.prototype.hasOwnProperty

export default function (ref) {
  return {
    data () {
      return {
        query: {
          pageSize: 10,
          pageNum: 1
        }
      }
    },

    methods: {
      /* Overrides
      --------------------------------------------------------------------------- */
      /**
       * 表格复选
       *
       * @param {Array} records
       */
      handleSelectionChange (records) {
        if (hasOwn.call(this, 'records')) {
          this.records = records
        }
      },

      /**
       * before
       *
       * @override
       */
      beforePageNumChange () {

      },

      /**
       * after
       *
       * @override
       */
      afterPageNumChange () {

      },

      /**
       * 搜索前置
       */
      beforeSearch (params) {
        return params
      },

      /**
       * 搜索后置
       */
      afterSearch () {

      },

      /**
       * 重置前置
       */
      beforeReset () {

      },

      /**
       * 重置后置
       */
      afterReset () {

      },

      /* Private Methods
      --------------------------------------------------------------------------- */
      /**
       * 获取实际查询参数
       *
       * @param {object: { pageNum, pageSize, any }} query
       */
      getActualParams (query) {
        const { pageSize, pageNum, ...rest } =
          (hasOwn.call(this, 'getRealQueryParams') && this.getRealQueryParams(this._query)) || this._query
        return {
          ...query,
          ...rest
        }
      },

      /**
       * 对字段进行监听更新_query对应字段
       *
       * 如点了树节点后,因直接发送了请求，故_query字段应该作同步修改
       * @param {array|string} field - 字段
       */
      addWatcher (fields) {
        if (typeof fields === 'string') {
          fields = fields.split(/ +/g)
        }
        fields.forEach(field => {
          const target = `query.${field}`
          this.$watch(target, (val) => {
            this._query[field] = val
          })
        })
      },

      /**
       * 分页改变时刷新数据
       *
       * @param {number} pageNum
       */
      handleCurrentChange (pageNum) {
        this.beforePageNumChange()
        this.query.pageNum = pageNum
        this.refresh(query => this.getActualParams({ ...this.beforeSearch(query), pageNum })).then(this.afterPageNumChange)
      },

      /**
       * 每页显示数改变
       *
       * @param {number} pageSize 当前每页显示数
       */
      handleSizeChange (pageSize) {
        this.query.pageSize = pageSize
        this.refresh(query => this.getActualParams({ ...this.beforeSearch(query), pageSize, pageNum: 1 }))
      },

      /**
       * 查询表格
       *
       * 始终从第一页开始刷新数据
       */
      handleSearch () {
        this._query = this.$cloneDeep(this.beforeSearch(this.query))
        // ? 请求成功后修改分页
        this.refresh(query => ({ ...this.beforeSearch(query), pageNum: 1 })).then(() => {
          this.query.pageNum = 1
        })

        this.afterSearch()
      },

      /**
       * 重置表格
       *
       * @param {string | array} keep 重置时保留的参数
       */
      async handleReset (keep = '') {
        if (typeof keep === 'string') {
          keep = keep.split(/ +/g)
        }
        if (keep.length) {
        } else {
          this.$refs[ref].resetFields()
        }
        this.query.pageNum = 1
        this.query.pageSize = this._query.pageSize
        this._query = this.$cloneDeep(this.beforeSearch(this.query))

        this.beforeReset()

        await this.refresh()

        this.afterReset()
      },

      /**
       * 注入请求并监听请求参数
       *
       * @param {Function} fn - 请求函数
       * @param {Sting[]} watchers - 监听请求参数变化更新_query对应字段
       */
      inject (fn, watchers) {
        this.refresh = fn

        if (watchers) {
          this.addWatcher(watchers)
        }
      }
    },

    computed: {
      bindListeners () {
        return {
          'selection-change': (...args) => this.handleSelectionChange(...args),
          'update:currentPage': (val) => {
            this.query.pageNum = val
          }
        }
      },
      bindProps () {
        return {
          currentPage: this.query.pageNum,
          pagination: {
            pageSize: this.query.pageSize
          },
          currentChange: (v) => this.handleCurrentChange(v),
          sizeChange: (v) => this.handleSizeChange(v)
        }
      }
    },

    mounted () {
      this._query = this.$cloneDeep(this.beforeSearch(this.query))
    }
  }
}
